package ru.teleology.cubefs.api.reflection;

import ru.teleology.cubefs.api.reflection.list.ListOfBigInt;
import ru.teleology.cubefs.api.reflection.list.ListOfStrings;
import ru.teleology.cubefs.api.reflection.list.ListOfTyped;
import ru.teleology.cubefs.api.reflection.list.ListOfTypes;
import ru.teleology.cubefs.api.reflection.list.StaticListOfTyped;
import ru.teleology.cubefs.api.reflection.number.BigIntNumber;
import ru.teleology.cubefs.api.reflection.number.ByteNumber;
import ru.teleology.cubefs.api.reflection.number.DoubleNumber;
import ru.teleology.cubefs.api.reflection.number.FloatNumber;
import ru.teleology.cubefs.api.reflection.number.IntNumber;
import ru.teleology.cubefs.api.reflection.number.ShortNumber;
import ru.teleology.cubefs.api.reflection.number.UShortNumber;
import ru.teleology.cubefs.api.reflection.value.BooleanValue;
import ru.teleology.cubefs.api.reflection.value.IDValue;
import ru.teleology.cubefs.api.reflection.value.StringValue;
import ru.teleology.cubefs.api.reflection.value.TypedIDValue;
import ru.teleology.cubefs.api.reflection.value.Version;
import ru.teleology.cubefs.api.reflection.value.VersionValue;

@NativeType(name = Types.CORE_FACTORY_TYPE)
public class CoreFactory extends Typed {

	public CoreFactory(long handle) {
		super(handle, false);
	}
	
	public ListOfTyped CreateListOfTyped(int size) 
	{
		return Types.getInstance(CreateListOfTyped(getHandle(), size));
	}
	
	public ListOfTyped CreateListOfTyped() {
		return CreateListOfTyped(-1);
	}
	
	public ListOfTypes CreateListOfTypes(int size) {
		return Types.getInstance(CreateListOfTypes(getHandle(), size));
	}
	
	public ListOfTypes CreateListOfTypes() {
		return CreateListOfTypes(-1);
	}
	
	public StaticListOfTyped CreateStaticListOfTyped() {
		return Types.getInstance(CreateStaticListOfTyped(getHandle()));
	}
	
	public ListOfStrings CreateListOfStrings(int size) 
	{
		return Types.getInstance(CreateListOfStrings(getHandle(), size));
	}
	
	public ListOfStrings CreateListOfStrings() {
		return CreateListOfStrings(-1);
	}
	
	public ListOfBigInt CreateListOfBigInt(int size) 
	{
		return Types.getInstance(CreateListOfBigInt(getHandle(), size));
	}
	
	public ListOfBigInt CreateListOfBigInt() {
		return CreateListOfBigInt(-1);
	}

	public ByteNumber Create(byte value) 
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public ShortNumber Create(short value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public UShortNumber Create(char value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public IntNumber Create(int value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public BigIntNumber Create(long value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public FloatNumber Create(float value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public DoubleNumber Create(double value)
	{
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public TypedIDValue Create(IDValue value) {
		return Types.getInstance(CreateIDValue(getHandle(), value.toString()));
	}
	
	public TypedIDValue CreateIDValue(String value) {
		return Types.getInstance(CreateIDValue(getHandle(), value));
	}
	
	public StringValue Create(String value) {
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public BooleanValue Create(boolean value) {
		return Types.getInstance(Create(getHandle(), value));
	}
	
	public VersionValue CreateVersion(String value)
	{
		return Types.getInstance(CreateVersion(getHandle(), value));
	}
	
	public VersionValue Create(Version value)
	{
		return Types.getInstance(CreateVersion(getHandle(), value.toString()));
	}

	public ru.teleology.cubefs.api.reflection.number.Number Create(java.lang.Number val) {
		if (val == null) {
			throw new RuntimeException("Argument must not be null");
		}
		else if (val instanceof Byte) {
			return Create(val.byteValue());
		}
		else if (val instanceof Short) {
			return Create(val.shortValue());
		}
		else if (val instanceof Integer) {
			return Create(val.intValue());
		}
		else if (val instanceof Long) {
			return Create(val.longValue());
		}
		else if (val instanceof Float) {
			return Create(val.floatValue());
		}
		else if (val instanceof Double) {
			return Create(val.doubleValue());
		}
		else {
			throw new RuntimeException("Unknown type of value: "+val.getClass());
		}
	}
	
	public UShortNumber Create(java.lang.Character val) {
		return Create(val.charValue());
	}
	
	public BooleanValue Create(java.lang.Boolean val) {
		return Create(val.booleanValue());
	}
	
	public TypeSystem GetCoreTypeSystem()
	{
		return Types.getInstance(getCoreTypeSystem());
	}
	
	public static CoreFactory GetCoreFactory() 
	{
		return Types.getInstance(getCoreFactory());
	}
	
	
	private static native long getCoreFactory();
	private static native long getCoreTypeSystem();
	
	private static native long CreateListOfTypes(long me, int size);
	private static native long CreateListOfTyped(long me, int size);
	private static native long CreateStaticListOfTyped(long me);
	private static native long CreateListOfStrings(long me, int size);
	private static native long CreateListOfBigInt(long me, int size);

	private static native long Create(long me, byte value);
	private static native long Create(long me, short value);
	private static native long Create(long me, char value);
	private static native long Create(long me, int value);
	private static native long Create(long me, long value);
	private static native long Create(long me, float value);
	private static native long Create(long me, double value);
	
	private static native long Create(long me, boolean value);
	private static native long Create(long me, String value);
	
	private static native long CreateIDValue(long me, String value);	
	private static native long CreateVersion(long me, String version);
}
